package oop.core.entity;

import oop.core.RunGame;

/**
 * Calculates all the derived stats and handles dealing with changes to stats that don't make sense for EntityStats
 */

public class DerivedStats extends Stats {
	/**
	 * @param exp
	 * @param livesLeft
	 * @param currHP
	 * @param currMP
	 * @param strength
	 * @param agility
	 * @param intellect
	 * @param hardiness
	 */
	public DerivedStats(int exp, int livesLeft, int currHP, int currMP,
			int strength, int agility, int intellect, int hardiness, long movement) {
		super(exp, livesLeft, currHP, currMP, strength, agility, intellect,
				hardiness, movement);
	}
	
	public DerivedStats(Stats stats){
		super(stats);
	}
	
	public int getNextLevelExperience() {
		return 1000 * (getLevel());
	}

	/**
	 * Returns the Defensive Rating of the entity - How likely it is to dodge.
	 * @return
	 */
	public int getDefensiveRating()
	{
		return (getAgility() * 2) + getLevel();
	}
	
	/**
	 * Returns the Offensive Rating of the entity - How likely it is to hit something.
	 * @return
	 */
	public int getOffensiveRating()
	{
		return (getStrength() * 2) + getLevel(); 
	}
	
	/**
	 * Returns the Armor Rating of the entity - The basis for how much damage reduction it has.
	 * @return
	 */
	public int getArmorRating()
	{
		return (getHardiness() / 5);
	}
	
	public int getMaxHP()
	{
		return (getHardiness() * 5) + (getLevel() * 10);
	}
	
	public int getMaxMP()
	{
		return (getIntellect() * 5) + (getLevel() * 10);
	}
	
	public int getLevel()
	{
		return (getEXP() / 1000) + 1;
	}

	public void giveEXP(int exp)
	{
		super.setEXP(super.getEXP() + exp);
	}
	
	/**
	 * Calculates how much damage the entity does in a normal attack
	 * @param passiveSkillLevel The skill proficiency for the attack type
	 * @return
	 */
	public int calcDamage(int passiveSkillLevel)
	{
		return (getStrength() * 2 + 10*passiveSkillLevel);
	}
	
	/**
	 * Lowers the entity's lives by lives and then sets their HP and MP to max
	 * @param lives
	 */
	public void die(int lives)
	{
		super.setLives(super.getLives() - lives);
		setHP(getMaxHP());
		setMP(getMaxMP());
	}
	
	/**
	 * Deals damage to the entity that ignores damage reduction
	 * @param dam
	 */
	public void takePiercingDamage(int dam)
	{
		setHP(getHP() - dam);
		if(getHP() <= 0)
		{
			die(1);
		}
	}
	/**
	 * Deals damage to the entity that is reduced by damage reduction
	 * @param dam
	 */
	public void takeDamage(int dam)
	{
		setHP(getHP() - (dam - getArmorRating()) );
		if(getHP() <= 0)
		{
			die(1);
		}
	}
	
	/**
	 * Reduces MP to a minimum of 0
	 * @param mana
	 */
	public void lowerMP(int mana)
	{
		setMP(getMP() - mana);
		if(getMP() <= 0)
		{
			setMP(0);
		}
	}
	
	public void takeLives(int numlives)
	{
		setLives(getLives() - numlives);
	}
	
	/**
	 * Uses the occupation's levelupstats to increase the entity's stts.
	 * @param levelStats
	 */
	public void doLevelUp(Stats levelStats)
	{
		super.setEXP(super.getEXP() + 1000);
		RunGame.println("You leveled up to level " + getLevel() + "!");
		setStrength(getStrength() + levelStats.getStrength());
		setAgility(getAgility() + levelStats.getAgility());
		setHardiness(getHardiness() + levelStats.getHardiness());
		setIntellect(getIntellect() + levelStats.getIntellect());
	}
	
	/**
	 * Heals the entity and does not let its HP go over its max health
	 * @param health
	 */
	public void heal(int health)
	{
		if((getHP() + health) > getMaxHP())
		{
			setHP(getMaxHP());
		} else
		{
			setHP(getHP() + health);
		}
	}
	
	/**
	 * Restores the entity's MP but does not let its MP go over its max MP.
	 * @param mana
	 */
	public void restoreMP(int mana)
	{
		if((getMP() + mana) > getMaxMP())
		{
			setHP(getMaxMP());
		} else
		{
			setMP(getMP() + mana);
		}
	}
	
	/**
	 * Used to increase an entity's stats when they equip things
	 * @param stats
	 */
	public void buffStats(Stats stats)
	{
	
		int currentexp = getEXP();
		int currentSTR = getStrength();
		int currentAGI = getAgility();
		int currentINT = getIntellect();
		int currentHAR = getHardiness();
		int currentLives = getLives();
		
		int buffHP = stats.getHP();
		int buffMP = stats.getMP();
		int buffexp = stats.getEXP();
		int buffSTR = stats.getStrength();
		int buffAGI = stats.getAgility();
		int buffINT = stats.getIntellect();
		int buffHAR = stats.getHardiness();
		int buffLives = stats.getLives();
		
		heal(buffHP);
		restoreMP(buffMP);
		super.setEXP(currentexp + buffexp);
		super.setStrength(currentSTR + buffSTR);
		super.setAgility(currentAGI + buffAGI);
		super.setIntellect(currentINT + buffINT);
		super.setHardiness(currentHAR + buffHAR);
		super.setLives(currentLives + buffLives);
	}
	
	/**
	 * The corollary call to buffStats when an entity unequips things.
	 * @param stats
	 */
	public void debuffStats(Stats stats)
	{
		int currentexp = getEXP();
		int currentSTR = getStrength();
		int currentAGI = getAgility();
		int currentINT = getIntellect();
		int currentHAR = getHardiness();
		int currentLives = getLives();
		
		int buffexp = stats.getEXP();
		int buffSTR = stats.getStrength();
		int buffAGI = stats.getAgility();
		int buffINT = stats.getIntellect();
		int buffHAR = stats.getHardiness();
		int buffLives = stats.getLives();
		
		super.setEXP(currentexp - buffexp);
		super.setStrength(currentSTR - buffSTR);
		super.setAgility(currentAGI - buffAGI);
		super.setIntellect(currentINT - buffINT);
		super.setHardiness(currentHAR - buffHAR);
		super.setLives(currentLives - buffLives);
	}
	
}